//
//  DKCoverFlow.m
//  DKCoverFlow
//
//  Created by 许建勇 on 15/5/21.
//  Copyright (c) 2015年 许建勇. All rights reserved.
//

#import "DKCoverFlow.h"

//-------------------------------------------------------
#pragma mark - 基类Cell
@implementation DKCoverFlowCell
- (instancetype)initWithReuseIdentifier:(NSString *)reuseIdentifier
{
    self=[super init];
    if(self)
    {
        self.reuseIdentifier=reuseIdentifier;
        self.index=-1;
    }
    return self;
}

@end
//-------------------------------------------------------




@implementation DKCoverFlow
#pragma mark - Init
- (void)initParameter
{
    //元素尺寸
    _cellSize=CGSizeMake(50, 50);
    
    //元素间隔
    _cellGap=10;
    
    //复用数组
    reusableCellArray=[[NSMutableArray alloc] init];
    
    //显示数组
    displayCellArray=[[NSMutableArray alloc] init];
    
    //元素个数
    pageNumber=0;
    
    //显示范围
    visibleRange=NSMakeRange(0, 0);

    //旋转方向
    _orientation=DKCoverFolowOrientationHorizontal;
    
    //委托模式
    _delegate=nil;
    _dataSource=nil;
    
    //缩放因子
    _scaleKey=0.8;
    
    //缩放因子递归
    _enableScaleRecursion=YES;
    
    //透明因子
    _alphaKey=0.5;
    
    //透明因子递归
    _enableAlphaRecursion=YES;
    
    //当前下标
    _index=0;
    
    //坐标修正
    _pagingEnable=true;
    
    //上一次页面的序号，用于didScrollPassByIndex的实现
    lastIndex=0;
}

- (void)initUI
{
    //滑动窗口
    _scrollView=[[UIScrollView alloc] init];
    _scrollView.delegate=self;
    [_scrollView setShowsHorizontalScrollIndicator:NO];
    [_scrollView setShowsVerticalScrollIndicator:NO];
    [_scrollView setDecelerationRate:kCoverFlowScrollPageDecelerationRate];
    [self addSubview:_scrollView];
}

#pragma mark - Layout
- (void)refreshLayout:(CGRect)frame
{
    _scrollView.frame=CGRectMake(0,
                                 0,
                                 frame.size.width,
                                 frame.size.height);
    
    if(frame.size.width>0  && frame.size.height>0)
    {
        [self reloadData];
    }
    
}



#pragma mark - Setter
- (void)setPagingEnable:(BOOL)pagingEnable
{
    _pagingEnable=pagingEnable;
    if(_pagingEnable)
    {
        [_scrollView setDecelerationRate:kCoverFlowScrollPageDecelerationRate];
    }
    else
    {
        [_scrollView setDecelerationRate:1.0];
    }
}


#pragma mark - Action
/**
 *  根据offset添加元素
 *
 *  @param offset 偏移
 */
- (void)refreshCellWithOffset:(CGPoint)offset
{
    switch (_orientation) {
        case DKCoverFolowOrientationHorizontal:
        {//水平方向
            //计算出显示在界面上的view序号，分别往两侧延伸一个，预加载提升体验
            NSInteger startIndex=MAX(0, (offset.x-_scrollView.frame.size.width/2)/(_cellSize.width+_cellGap));
            NSInteger endIndex=MIN(pageNumber-1, (offset.x+_scrollView.frame.size.width/2)/(_cellSize.width+_cellGap)+1);
            
            //删除多余的界面上的cell
            for(NSInteger i=displayCellArray.count-1;i>=0;i--)
            {
                DKCoverFlowCell* temp=displayCellArray[i];
                if(temp.index<startIndex || temp.index>endIndex)
                {//删除该元素
                    [temp removeFromSuperview];
                    [displayCellArray removeObject:temp];
                    //删除的元素推入回收栈中
                    temp.layer.transform=CATransform3DMakeScale(1, 1, 1);//恢复缩放
                    temp.alpha=1.0;//恢复透明度
                    [reusableCellArray addObject:temp];
                }
            }
            
            //重新添加元素
            for(NSInteger i=startIndex;i<=endIndex;i++)
            {
                if(NSLocationInRange(i, visibleRange))
                {//如果要生成的元素已显示，不需要改变
                    
                }
                else
                {//生成的元素不在，则需要重新生成
                    DKCoverFlowCell* cell=[_dataSource coverFlow:self forIndex:i];
                    cell.frame=CGRectMake(_scrollView.frame.size.width/2+i*(_cellSize.width+_cellGap)-_cellSize.width/2,
                                          (_scrollView.frame.size.height-_cellSize.height)/2,
                                          _cellSize.width,
                                          _cellSize.height);
                    cell.index=i;
                    [displayCellArray addObject:cell];
                    [_scrollView addSubview:cell];
                }
            }
            
            //重新设定可视范围
            visibleRange=NSMakeRange(startIndex, endIndex-startIndex+1);
            
            break;
        }
        default:
        {//竖直方向
            //计算出显示在界面上的view序号，分别往两侧延伸一个，预加载提升体验
            NSInteger startIndex=MAX(0, (offset.y-_scrollView.frame.size.height/2)/(_cellSize.height+_cellGap));
            NSInteger endIndex=MIN(pageNumber-1, (offset.y+_scrollView.frame.size.height/2)/(_cellSize.height+_cellGap)+1);
            
            //删除多余的界面上的cell
            for(NSInteger i=displayCellArray.count-1;i>=0;i--)
            {
                DKCoverFlowCell* temp=displayCellArray[i];
                if(temp.index<startIndex || temp.index>endIndex)
                {//删除该元素
                    [temp removeFromSuperview];
                    [displayCellArray removeObject:temp];
                    //删除的元素推入回收栈中
                    temp.layer.transform=CATransform3DMakeScale(1, 1, 1);//恢复缩放
                    temp.alpha=1.0;//恢复透明度
                    [reusableCellArray addObject:temp];
                }
            }
            
            //重新添加元素
            for(NSInteger i=startIndex;i<=endIndex;i++)
            {
                if(NSLocationInRange(i, visibleRange))
                {//如果要生成的元素已显示，不需要改变
                    
                }
                else
                {//生成的元素不在，则需要重新生成
                    DKCoverFlowCell* cell=[_dataSource coverFlow:self forIndex:i];
                    cell.frame=CGRectMake((_scrollView.frame.size.width-_cellSize.width)/2,
                                          _scrollView.frame.size.height/2+i*(_cellSize.height+_cellGap)-_cellSize.height/2,
                                          _cellSize.width,
                                          _cellSize.height);
                    cell.index=i;
                    [displayCellArray addObject:cell];
                    [_scrollView addSubview:cell];
                }
            }
            
            //重新设定可视范围
            visibleRange=NSMakeRange(startIndex, endIndex-startIndex+1);
            
            break;
        }
    }
}


/**
 *  绘制每个cell的样式
 */
- (void)refreshVisibleCellAppearance
{
    for(int i=0;i<displayCellArray.count;i++)
    {
        DKCoverFlowCell* cell=displayCellArray[i];
        CGFloat distance=0;//距离中心位置的距离
        CGFloat delta=0;//距离中心位置的比例
        switch (_orientation) {
            case DKCoverFolowOrientationHorizontal:
            {//水平方向
                distance=fabs(_scrollView.contentOffset.x+_scrollView.frame.size.width/2-cell.center.x);
                delta=distance/(_cellSize.width+_cellGap);
                break;
            }
            default:
            {//竖直方向
                distance=fabs(_scrollView.contentOffset.y+_scrollView.frame.size.height/2-cell.center.y);
                delta=distance/(_cellSize.height+_cellGap);
                break;
            }
        }

        CGFloat scaleDelta=delta;
        if(scaleDelta>1 && _enableScaleRecursion==false)
        {//非主要元素统一大小
            scaleDelta=1;
        }
        CGFloat scaleNow=pow(_scaleKey, floor(scaleDelta));
        CGFloat scaleNext=pow(_scaleKey, floor(scaleDelta)+1);
        CGFloat scaleRest=scaleDelta-floor(scaleDelta);
        cell.layer.transform = CATransform3DMakeScale(scaleNow-scaleRest*(scaleNow-scaleNext), scaleNow-scaleRest*(scaleNow-scaleNext), 1);


        
        CGFloat alphaDelta=delta;
        if(alphaDelta>1 && _enableAlphaRecursion==false)
        {
            alphaDelta=1;
        }
        CGFloat alphaNow=pow(_alphaKey, floor(alphaDelta));
        CGFloat alphaNext=pow(_alphaKey, floor(alphaDelta)+1);
        CGFloat alphaRest=alphaDelta-floor(alphaDelta);
        cell.alpha=alphaNow-alphaRest*(alphaNow-alphaNext);
    }
}





#pragma mark - UIScrollViewDelegate
-(void)scrollViewDidScroll:(UIScrollView *)scrollViews
{
    if(scrollViews.isDecelerating || scrollViews.isDragging)
    {//如果是用户操作而不是scrollToRow函数造成的滚动
        NSInteger nowIndex=0;
        switch (_orientation) {
            case DKCoverFolowOrientationHorizontal:
            {//水平方向
                nowIndex=round((scrollViews.contentOffset.x)/(_cellGap+_cellSize.width));
                break;
            }
            default:
            {//竖直方向
                nowIndex=round((scrollViews.contentOffset.y)/(_cellGap+_cellSize.height));
                break;
            }
        }
        if(lastIndex!=nowIndex)
        {
            lastIndex=nowIndex;
            if([_delegate respondsToSelector:@selector(coverFlow:didScrollPassByIndex:)])
            {
                [_delegate coverFlow:self didScrollPassByIndex:nowIndex];
            }
        }
    }

    [self refreshCellWithOffset:scrollViews.contentOffset];
    [self refreshVisibleCellAppearance];
}

-(void)scrollViewDidEndDragging:(UIScrollView *)scrollViews willDecelerate:(BOOL)decelerate
{
    if(_pagingEnable)
    {
        dispatch_async(dispatch_get_main_queue(), ^{
            [scrollViews setContentOffset:scrollViews.contentOffset animated:NO];
            
            
            //优化滑动体验，计算当前页面的中心序号，如果不同则不操作，如果相同，根据移动方向自动移动一个单位
            NSInteger nowIndex=0;
            switch (_orientation) {
                case DKCoverFolowOrientationHorizontal:
                {//水平方向
                    nowIndex=round((scrollViews.contentOffset.x)/(_cellGap+_cellSize.width));
                    break;
                }
                default:
                {//竖直方向
                    nowIndex=round((scrollViews.contentOffset.y)/(_cellGap+_cellSize.height));
                    break;
                }
            }
            if(nowIndex==_index)
            {
                switch (_orientation) {
                    case DKCoverFolowOrientationHorizontal:
                    {//水平方向
                        if((_cellSize.width+_cellGap)*nowIndex<scrollViews.contentOffset.x)
                        {
                            nowIndex++;
                        }
                        else if((_cellSize.width+_cellGap)*nowIndex>scrollViews.contentOffset.x)
                        {
                            nowIndex--;
                        }
                        break;
                    }
                    default:
                    {//竖直方向
                        if((_cellSize.height+_cellGap)*nowIndex<scrollViews.contentOffset.y)
                        {
                            nowIndex++;
                        }
                        else if((_cellSize.height+_cellGap)*nowIndex>scrollViews.contentOffset.y)
                        {
                            nowIndex--;
                        }
                        break;
                    }
                }
            }
            
            
            nowIndex=MIN(pageNumber-1, MAX(0, nowIndex));
            _index=nowIndex;

            [self scrollToRow:_index];
            
            if([_delegate respondsToSelector:@selector(coverFlow:didScrollToIndex:)])
            {
                [_delegate coverFlow:self didScrollToIndex:_index];
            }
        });
        
    }
    else if(!decelerate)
    {
        [self scrollViewDidStop:scrollViews];
    }
}


-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollViews
{
    if(!_pagingEnable)
    {
        [self scrollViewDidStop:scrollViews];
    }
}



/**
 *  滑动停止的位置
 *
 *  @param scrollViews 滚动视图
 */
-(void)scrollViewDidStop:(UIScrollView*)scrollViews
{
    NSInteger nowIndex=0;
    switch (_orientation) {
        case DKCoverFolowOrientationHorizontal:
        {//水平方向
            nowIndex=round((scrollViews.contentOffset.x)/(_cellGap+_cellSize.width));
            break;
        }
        default:
        {//竖直方向
            nowIndex=round((scrollViews.contentOffset.y)/(_cellGap+_cellSize.height));
            break;
        }
    }
    _index=nowIndex;
    if([_delegate respondsToSelector:@selector(coverFlow:didScrollToIndex:)])
    {
        [_delegate coverFlow:self didScrollToIndex:_index];
    }
}





#pragma mark - API
/**
 *  刷新视图
 */
- (void)reloadData
{
    //更新cell数量
    pageNumber=[_dataSource numberOfRowsInCoverFlow:self];
    
    
    //丢弃所有显示
    for(NSInteger i=displayCellArray.count-1;i>=0;i--)
    {
        DKCoverFlowCell* temp=displayCellArray.lastObject;
        [temp removeFromSuperview];
        [displayCellArray removeLastObject];
        //删除的元素推入回收栈中
        temp.layer.transform=CATransform3DMakeScale(1, 1, 1);//恢复缩放
        temp.alpha=1.0;//恢复透明度
        [reusableCellArray addObject:temp];
    }
    visibleRange=NSMakeRange(0, 0);
    
    
    //重新设置scroll的显示宽度
    switch (_orientation) {
        case DKCoverFolowOrientationHorizontal:
        {//水平方向_scrollView
            _scrollView.contentSize=CGSizeMake(_scrollView.frame.size.width+(pageNumber-1)*(_cellGap+_cellSize.width),_scrollView.frame.size.height);
            break;
        }
        default:
        {//垂直方向
            _scrollView.contentSize=CGSizeMake(_scrollView.frame.size.width,_scrollView.frame.size.height+(pageNumber-1)*(_cellGap+_cellSize.height));
            break;
        }
    }
    
    [self refreshCellWithOffset:_scrollView.contentOffset];
    
    [self refreshVisibleCellAppearance];
}

/**
 *  刷新视图
 *
 *  @param index 待刷新cell坐标
 */
- (void)reloadDataWithIndex:(NSInteger)index
{
    for(NSInteger k=0;k<displayCellArray.count;k++)
    {
        DKCoverFlowCell* temp=displayCellArray[k];
        if(temp.index==index)
        {
            //丢弃原视图
            [temp removeFromSuperview];
            [displayCellArray removeObjectAtIndex:k];
            //删除的元素推入回收栈中
            temp.layer.transform=CATransform3DMakeScale(1, 1, 1);//恢复缩放
            temp.alpha=1.0;//恢复透明度
            [reusableCellArray addObject:temp];
            
            
            //生成新视图
            DKCoverFlowCell* cell=[_dataSource coverFlow:self forIndex:index];
            cell.frame=CGRectMake(_scrollView.frame.size.width/2+index*(_cellSize.width+_cellGap)-_cellSize.width/2,
                                  (_scrollView.frame.size.height-_cellSize.height)/2,
                                  _cellSize.width,
                                  _cellSize.height);
            cell.index=index;
            [displayCellArray addObject:cell];
            [_scrollView addSubview:cell];
            
            [self refreshVisibleCellAppearance];
            break;
        }
    }
}




/**
 *  根据id获取cell
 *
 *  @param identifier 服用标示
 *
 *  @return cell
 */
- (id)dequeueReusableCellWithIdentifier:(NSString *)identifier
{
    DKCoverFlowCell* result=nil;
    for(int i=0;i<reusableCellArray.count;i++)
    {
        DKCoverFlowCell* temp=reusableCellArray[i];
        if([temp.reuseIdentifier isEqualToString:identifier])
        {
            result=temp;
            [reusableCellArray removeObject:temp];
        }
    }
    return result;
}

/**
 *  滚到到指定row
 *
 *  @param row 下标
 */
- (void)scrollToRow:(NSInteger)row
{
    [self scrollToRow:row Animated:YES];
}

/**
 *  滚动到指定row
 *
 *  @param row        下标
 *  @param isAnimated 是否播放动画
 */
- (void)scrollToRow:(NSInteger)row Animated:(BOOL)isAnimated
{
    if(row<0 || row>=pageNumber)
    {//不存在的对象不响应
        return;
    }
    
    CGPoint targetPoint;
    switch (_orientation) {
        case DKCoverFolowOrientationHorizontal:
        {//水平方向
            targetPoint=CGPointMake(row*(_cellGap+_cellSize.width), 0);
            break;
        }
        default:
        {//竖直方向
            targetPoint=CGPointMake(0,row*(_cellGap+_cellSize.height));
            break;
        }
    }
    [_scrollView setContentOffset:targetPoint animated:isAnimated];
    _index=row;
    lastIndex=row;
}

/**
 *  获取指定位置cell
 *
 *  @param index 位置
 *
 *  @return cell
 */
- (DKCoverFlowCell *)cellForIndex:(NSInteger)index
{
    for(int i=0;i<displayCellArray.count;i++)
    {
        DKCoverFlowCell *cell=displayCellArray[i];
        if(cell.index==index)
        {
            return cell;
        }
    }
    return nil;
}

@end
